﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ttlang.compiler
{


    //添加一個特別數據結構，可以隨機訪問的棧

    public class TempVarContext
    {
        public ttlang.semantic.TTType type;
        public string id;
        public TempVarContext(string _id, ttlang.semantic.TTType _type)
        {
            this.id = _id;
            this.type = _type;
        }
    }
    public class BlockContext
    {
        public BlockContext()
        {
            vars = new Dictionary<string, TempVarContext>();
        }
        public Dictionary<string, TempVarContext> vars;

        public bool FindTempVar(string id, out TempVarContext v)
        {
            return vars.TryGetValue(id, out v);
        }

    }


    public class CompilerContext
    {
        //会根据函数内的临时上下文和 module 来寻找语义
        public semantic.Module module;//语义节点，都是定义，这里列出整个项目所有的公共语义节点，函数内的不算

        public string projectRoot;

        public RandomStack<semantic.TTNameSpace> stack_namespace;
        public RandomStack<string> stack_using;
        public RandomStack<semantic.TTType> stack_class;
        public RandomStack<string> stack_comment;//注释栈,把注释分给各种结构节点
        private RandomStack<BlockContext> stack_blocks;
        public RandomStack<semantic.TTMethod> stack_method;

        public node.Node resultNode;
        public CompileState state;
        public List<CompileLog> logs;

        public ProjectOption projectOption;
        public CompilerContext()
        {
            state = CompileState.NONE;
            logs = new List<CompileLog>();
            module = new semantic.Module("__noname");

            projectRoot = "";
            stack_namespace = new RandomStack<semantic.TTNameSpace>();
            stack_using = new RandomStack<string>();
            stack_class = new RandomStack<semantic.TTType>();
            stack_blocks = new RandomStack<BlockContext>();
            stack_comment = new RandomStack<string>();
            stack_method = new RandomStack<semantic.TTMethod>();
        }
        public semantic.IContainer GetParentContainer()
        {
            if (stack_class.Count > 0)
                return stack_class.Peek();
            if (stack_namespace.Count > 0)
                return stack_namespace.Peek();
            return module._defNameSpace;
        }

        public void PushBlock()
        {
            stack_blocks.Push(new BlockContext());
        }
        public void PopBlock()
        {
            stack_blocks.Pop();
        }

        public void PushNameSpace(semantic.TTNameSpace _namespace)
        {
            stack_namespace.Push(_namespace);
        }
        public void PopNameSpace()
        {
            stack_namespace.Pop();
        }
        public void PushMethod(semantic.TTMethod _method)
        {
            stack_method.Push(_method);
        }
        public void PopMethod()
        {
            stack_method.Pop();
        }
        public void PushClass(semantic.TTType _type)
        {
            stack_class.Push(_type);
        }
        public void PopClass()
        {
            stack_class.Pop();
        }
        public void RegTempVar(string name, semantic.TTType _type)
        {
            if (FindTempVar(name, out _) != false)
                throw new Exception("already had a var had defined:" + name);

            var curblock = stack_blocks.Peek();
            var vartype = new TempVarContext(name, _type);
            curblock.vars[name] = vartype;
        }
        //尝试获取临时变量
        public bool FindTempVar(string id, out TempVarContext v)
        {
            for (var i = stack_blocks.Count - 1; i >= 0; i--)
            {
                if (stack_blocks[i].FindTempVar(id, out v))
                    return true;
            }
            v = null;
            return false;
        }
        public bool FindMethod(string id, out semantic.TTMethod method)
        {
            var allmodule = semantic.Module.GetAllModules(module);
            //要考虑所有using
            //当前namespace 和 class
            //这里简单实现，并没有完成
            foreach (var m in allmodule)
            {
                if (m.FindMethod(id, out method))
                    return true;
            }
            ////所有命名空间检查
            //for (var i = 0; i < stack_namespace.Count; i++)
            //{
            //    var _namespace = stack_namespace.Peek(i);
            //    if (_namespace.FindMethod(id, out method))
            //        return true;
            //}


            ////所有class检查
            //for (var i = 0; i < stack_class.Count; i++)
            //{
            //    var _class = stack_class.Peek(i);
            //    if (_class.FindMethod(id, out method))
            //        return true;
            //}
            method = null;
            return false;

        }
        public bool FindArg(string id, out semantic.TTArg arg)
        {
            arg = null;
            var _method = this.stack_method.Peek();
            if (_method != null)
            {
                foreach(var marg in _method.args)
                {
                    if (id == marg.name)
                    {
                        arg = marg;
                        return true;
                    }
                }
            }

            return false;

        }
        public bool FindVar(string id, out semantic.TTVar var)
        {
            var allmodule = semantic.Module.GetAllModules(module);
            //要考虑所有using
            //当前namespace 和 class
            //这里简单实现，并没有完成
            foreach (var m in allmodule)
            {
                if (m.FindVar(id, out var))
                    return true;
            }

            //所有命名空间检查
            for (var i = 0; i < stack_namespace.Count; i++)
            {
                var _namespace = stack_namespace.Peek(i);
                if (_namespace.FindVar(id, out var))
                    return true;
            }


            //所有class检查
            for (var i = 0; i < stack_class.Count; i++)
            {
                var _class = stack_class.Peek(i);
                if (_class.FindVar(id, out var))
                    return true;
            }
            var = null;
            return false;

        }
        public bool FindMember(string id, out semantic.IMember member)
        {
            if (FindMethod(id, out var _m) && _m != null)
            {
                member = _m;
                return true;
            }
            else if (FindVar(id, out var _v) && _v != null)
            {
                member = _v;
                return true;
            }
            else
            {
                member = null;
                return false;
            }
        }
        public bool FindType(string id, out semantic.TTType outtype)
        {
            var allmodule = semantic.Module.GetAllModules(module);
            //要考虑所有using
            //当前namespace 和 class
            //这里简单实现，并没有完成

            //默认命名空间检查
            foreach (var m in allmodule)
            {
                if (m.FindType(id, out outtype))
                    return true;
            }

            //所有命名空间检查
            for (var i = 0; i < stack_namespace.Count; i++)
            {
                var _namespace = stack_namespace.Peek(i);
                if (_namespace.FindType(id, out outtype))
                    return true;
            }


            //所有class检查
            for (var i = 0; i < stack_class.Count; i++)
            {
                var _class = stack_class.Peek(i);
                if (_class.FindType(id, out outtype))
                    return true;
            }

            outtype = null;
            return false;
        }

        public bool FindNameSpace(string id, out semantic.TTNameSpace outtype)
        {
            //要考虑所有using
            //当前namespace 和 class
            //这里简单实现，并没有完成
            var allmodule = semantic.Module.GetAllModules(module);
            foreach (var m in allmodule)
            {
                if (m.FindNameSpace(id, out outtype))
                    return true;
            }
            for (var i = 0; i < stack_namespace.Count; i++)
            {
                // peek 取出堆栈中的栈顶得元素，但不删除
                var _namespace = stack_namespace.Peek(i);
                if (_namespace.FindNamespace(id, out outtype))
                {
                    return true;
                }
            }
            outtype = null;
            return false;
        }
    }
}
